import {
  NPagination,
  type PaginationProps,
  type PaginationRenderLabel,
  type PaginationInfo,
} from "naive-ui";
import type { BaseComponentType, OmitHTMLAttributes } from "../types";
import { getSlotsDom } from "../utils";

export type PaginationFactoryConstructorType = {
  props?: PaginationProps;
  attrs?: OmitHTMLAttributes<"prefix" | "onChange">;
  gotoSlot?: BaseComponentType;
  labelSlot?: (v?: PaginationRenderLabel) => BaseComponentType;
  nextSlot?: (v?: PaginationInfo) => BaseComponentType;
  prevSlot?: (v?: PaginationInfo) => BaseComponentType;
  prefixSlot?: (v?: PaginationInfo) => BaseComponentType;
  suffixSlot?: (v?: PaginationInfo) => BaseComponentType;
};

export class PaginationFactory {
  private props: PaginationProps = {};
  private attrs: OmitHTMLAttributes<"prefix" | "onChange"> = {};
  private gotoSlot: BaseComponentType = null;
  private labelSlot: (v?: PaginationRenderLabel) => BaseComponentType = () =>
    null;
  private nextSlot: (v?: PaginationInfo) => BaseComponentType = () => null;
  private prevSlot: (v?: PaginationInfo) => BaseComponentType = () => null;
  private prefixSlot: (v?: PaginationInfo) => BaseComponentType = () => null;
  private suffixSlot: (v?: PaginationInfo) => BaseComponentType = () => null;

  constructor(data?: PaginationFactoryConstructorType) {
    if (data?.props) this.setProps(data.props);
    if (data?.attrs) this.setAttrs(data.attrs);
    if (data?.gotoSlot) this.setGoto(data.gotoSlot);
    if (data?.labelSlot) this.setLabel(data.labelSlot);
    if (data?.nextSlot) this.setNext(data.nextSlot);
    if (data?.prevSlot) this.setPrev(data.prevSlot);
    if (data?.prefixSlot) this.setPrefix(data.prefixSlot);
    if (data?.suffixSlot) this.setSuffix(data.suffixSlot);
  }

  setAttrs(attrs: OmitHTMLAttributes<"prefix" | "onChange">) {
    this.attrs = attrs;
    return this;
  }

  setProps(props: PaginationProps) {
    this.props = props;
    return this;
  }

  setGoto(slot: BaseComponentType) {
    this.gotoSlot = slot;
    return this;
  }

  setLabel(slot: (v?: PaginationRenderLabel) => BaseComponentType) {
    this.labelSlot = slot;
    return this;
  }

  setNext(slot: (v?: PaginationInfo) => BaseComponentType) {
    this.nextSlot = slot;
    return this;
  }

  setPrev(slot: (v?: PaginationInfo) => BaseComponentType) {
    this.prevSlot = slot;
    return this;
  }

  setPrefix(slot: (v?: PaginationInfo) => BaseComponentType) {
    this.prefixSlot = slot;
    return this;
  }

  setSuffix(slot: (v?: PaginationInfo) => BaseComponentType) {
    this.suffixSlot = slot;
    return this;
  }

  create() {
    return (
      <NPagination {...this.attrs} {...this.props}>
        {{
          goto: this.gotoSlot != null ? () => getSlotsDom(this.gotoSlot) : null,

          label:
            this.labelSlot() != null
              ? (v: PaginationRenderLabel) => getSlotsDom(this.labelSlot(v))
              : null,

          next:
            this.nextSlot() != null
              ? (info: PaginationInfo) => getSlotsDom(this.nextSlot(info))
              : null,

          prev:
            this.prevSlot() != null
              ? (info: PaginationInfo) => getSlotsDom(this.prevSlot(info))
              : null,

          prefix:
            this.prefixSlot() != null
              ? (info: PaginationInfo) => getSlotsDom(this.prefixSlot(info))
              : null,

          suffix:
            this.suffixSlot() != null
              ? (info: PaginationInfo) => getSlotsDom(this.suffixSlot(info))
              : null,
        }}
      </NPagination>
    );
  }
}
